package com.download.download;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;

import com.download.exception.DownloadException;
import com.download.utils.HttpUtil;
import com.download.utils.LogUtil;

public class SingleThreadDownload implements Runnable {

    // 缓冲区
    private static final int BUFF_SIZE = 1024 * 8;
    private byte[] buffer = new byte[BUFF_SIZE];
    // 下载地址
    private String url;
    // 起始点
    private long startPosition;
    // 结束点
    private long endPosition;
    // 文件碎片
    private FileBlock fileBlock;
    // 线程编号
    private int threadId;
    // 下载是否完成
    private boolean isFinished = false;
    //HTTP连接
    private HttpURLConnection conn;
    //HTTP状态码
    private int responseCode;
    //输入流用来接收HTTP输入流
    private InputStream inputStream;

    /**
     * @param threadId 线程id
     * @param url 下载地址
     * @param startPosition 写入点开始位置
     * @param endPosition 写入点结束位置
     * @param name 包含文件存储路径的文件名
     * @throws IOException 
     * @throws Exception
     */
    public SingleThreadDownload(int threadId, String url, long startPosition,
        long endPosition, String fileName) throws IOException  {
        this.threadId = threadId;
        this.url = url;
        this.startPosition = startPosition;
        this.endPosition = endPosition;
        this.fileBlock = new FileBlock(fileName, startPosition);
    }

    @Override
    public void run() {
        try {
                LogUtil.info("[线程" + threadId + "]：将要下载["+startPosition + "-" + endPosition + "]，共【" +  (endPosition-startPosition+1) +"】个字节！");
                //下载完成时startPosition比endPostion大1
            while (startPosition - endPosition != 1) {
                initHttpConnection();
                responseCode = conn.getResponseCode();
                //200仅适用于不支持多线程下载的文件
                if (responseCode == 206 || responseCode == 200) {
                    readInputStream(conn);
                    this.isFinished = true;
                } else {
                    LogUtil.info("下载失败，响应信息如下：");
                    //连接异常打印相应头
                    HttpUtil.printResponseInfo(conn);
                }
            }
        } catch (IOException e) {
            throw new DownloadException("SingleThreadDownload.run() try", e);
        } finally {
            try {
                close();
            } catch (IOException e) {
                LogUtil.info(e);
            }
        }
    }

    /**
     * @return
     * @throws IOException 
     */
    public void initHttpConnection() throws IOException {
        conn = HttpUtil.getHttpConnection(this.url);
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
    }

    /**
     * 读取输入流
     * @param conn
     * @throws IOException
     */
    public void readInputStream(HttpURLConnection conn) throws IOException{
        inputStream = conn.getInputStream();
        int len = -1;
        while ((len = inputStream.read(buffer)) != -1) {
            startPosition += fileBlock.write(buffer, 0, len); // 累加已经下载的字节数
        }
    }

    /**
     * 关闭资源
     * @throws IOException
     */
    public void close() throws IOException{
        if (fileBlock != null) {
            fileBlock.close();
        }
        if (inputStream != null) {
            inputStream.close();
        }
        if(conn != null){
            HttpUtil.disconnect(conn);
        }
    }

    public long getStartPosition() {
        return startPosition;
    }

    public boolean isFinished() {
        return isFinished;
    }

}